/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef XMCHANNEL_H
#define XMCHANNEL_H

#include "Pattern.h"
#include "RunningEnvelope.h"
#include "XMInstrument.h"

#include "Format.h"

class XMPlayer;

class XMChannel
{
	XMPlayer * const xm_player;

	int position;
	int old_position;
	int increase;

	void * sample_data;
	int sample_length;
	int sample_loop_start;

	int sample_type;

	int mix_to_left;
	int mix_to_right;
	//stereo
	int total_to_left;
	int total_to_right;
	//mono
	int total_to_mono;

	int panning;	//int left channel, range: 0 - 255

	int current_volume_fade;
	int volume_fade;

	RunningEnvelope volume_envelope;
	RunningEnvelope panning_envelope;

	bool key_off;

	int volume;
	int old_volume;
	unsigned current_volume;

	int volume_slide;
	int old_volume_slide;

	int global_volume_slide;
	int old_global_volume_slide;

	int panning_slide;
	int old_panning_slide;

	int period;
	int old_period;

	int frequency_slide;
	int old_frequency_slide;

	int portamento_dest;
	int portamento_slide;

	int vibrato_pos;
	int virato_slide;
	int vibrato_type;

	int tremolo_pos;
	int tremolo_slide;
	int tremolo_type;

	int count5;
	int count4;
	int count3;
	int count2;
	int count1;
	int period1;
	int period2;

	int fine_tune;
	
	int old_instrument_number;

	bool is_portamento;
	bool is_fine_vibrato;
	bool is_vibrato;
	bool is_tremolo;

	bool is_volume_slide;
	bool is_panning_slide;
	bool is_frequency_slide;

	int channel_number;

	void set_key_off();
	void reset();
	void set_instrument_and_sample( int instrument_number, const XMInstrument::XMSample * sample, bool selected_old_instrument );

	template< typename Dst, typename Src, bool Stereo >
	void mix_samples( Dst * dst, Src * sample_data, int position, int samples_predicted );

public:
	XMChannel( XMPlayer * xm_player, int channel_number )//, Mixer * mixer, const Format & format )
	:	xm_player( xm_player ),
		channel_number( channel_number ),
		key_off( false ),
		old_instrument_number( 0 ),
		sample_data( 0 ),
		sample_length( 0 ),
		current_volume( 0 ),
		volume( 0 ),
		mix_to_left( 0 ),
		mix_to_right( 0 )
	{}
	void update_tick();
	void update_volume();
	void update_note( const Note & note );
	void calculate_volume();

	void decode( void * where, int samples_count, const Format & format, bool interpolate );
};


#endif //XMCHANNEL_H